#include "io_sock.h"
#include "task.h"
#include "frame.h"
#include "frame_list.h"

static void *serv_task_func(void *arg)
{
    sock_t *serv = (sock_t *)arg;

    while(1){
        sock_t *cli = sock_accept(serv);
        if(!cli){
            ERR("sock_accept fail");
            break;
        }

        while(1){
            frame_t *frame = frame_new(0);
            assert(frame);
            
            int ret = frame_receive(frame, sock_fd(cli));
            if(ret < 0){
                ERR("frame_receive fail");
                frame_destroy(&frame);
                break;
            }

            if(ret == 0){
                DBG("client closed");
                frame_destroy(&frame);
                break;
            }

            if(frame_send(frame, sock_fd(cli)) < 0){
                ERR("frame_send fail");
                frame_destroy(&frame);
                break;
            }
        }

        sock_destroy(&cli);
    }

    return NULL;
}

int sock_frame_test(void)
{
    printf("** sock & frame test:\n");
    sock_t *serv = sock_new("@tcp:127.0.0.1:8000");
    sock_t *cli = sock_new(">tcp:127.0.0.1:8000");

    assert(serv);
    assert(cli);

    task_t *serv_task = task_create("serv_task", serv_task_func, serv);
    assert(serv_task);

    char *data = "hello frame module";
    size_t len = strlen(data)+1;
    frame_t *frame = frame_new_with_data(data, len);
    assert(frame);

    assert(frame_send(frame, sock_fd(cli)) == len);
    frame_destroy(&frame);
        
    frame_t *reply = frame_new(0);
    assert(frame_receive(reply, sock_fd(cli)) == len);
    printf("data: %s\n", (char *)frame_data(reply));
    frame_destroy(&reply);

    sock_destroy(&cli);
    task_destroy(&serv_task, NULL, 1);
    sock_destroy(&serv);

    printf("** sock & frame test success\n");
    return 0;
}

int sock_frame_list_test(void)
{
    printf("** sock & frame_list test:\n");
    sock_t *serv = sock_new("@tcp:127.0.0.1:8000");
    sock_t *cli = sock_new(">tcp:127.0.0.1:8000");

    assert(serv);
    assert(cli);

    task_t *serv_task = task_create("serv_task", serv_task_func, serv);
    assert(serv_task);

    frame_list_t *flist = frame_list_new();
    assert(flist);

    assert(frame_list_add_str_frame(flist, "the first message") == 0);
    assert(frame_list_add_str_frame(flist, "the second message") == 0);
    assert(frame_list_add_frame_begin(flist) == 0);
    assert(frame_list_add_frame_data(flist, "one line ", strlen("one line ")) == 0);
    assert(frame_list_add_frame_data(flist, "two line", strlen("two line")+1) == 0);
    assert(frame_list_add_frame_end(flist) == 0);

    assert(frame_list_send(flist, sock_fd(cli)) == 0);
    frame_list_destroy(&flist);

    frame_t *reply;
    int i;
    for(i = 0; i < 3; ++i){
        reply = frame_new(0);
        assert(reply);
        assert(frame_receive(reply, sock_fd(cli)) > 0);
        printf("data: %s\n", (char *)frame_data(reply));
        frame_destroy(&reply);
    }

    sock_destroy(&cli);
    task_destroy(&serv_task, NULL, 1);
    sock_destroy(&serv);

    printf("** sock & frame_list test success\n");
    return 0;
}

